home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / source / trans / dib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-12  |  23.6 KB  |  972 lines

  1. /*----------------------------------------------------------------------------*\
  2. |   Routines for dealing with Device independent bitmaps                       |
  3. \*----------------------------------------------------------------------------*/
  4.  
  5. #include <windows.h>
  6. #include <windowsx.h>
  7. #include "dib.h"
  8.  
  9. #ifdef WIN32
  10.     #include <memory.h>             // for _fmemcpy()
  11.     #define _huge
  12.     #define hmemcpy memcpy
  13. #endif
  14.  
  15. #define BFT_ICON   0x4349   /* 'IC' */
  16. #define BFT_BITMAP 0x4d42   /* 'BM' */
  17. #define BFT_CURSOR 0x5450   /* 'PT' */
  18.  
  19. /* flags for _lseek */
  20. #define  SEEK_CUR 1
  21. #define  SEEK_END 2
  22. #define  SEEK_SET 0
  23.  
  24. /*
  25.  *   Open a DIB file and return a MEMORY DIB, a memory handle containing..
  26.  *
  27.  *   BITMAP INFO    bi
  28.  *   palette data
  29.  *   bits....
  30.  *
  31.  */
  32. PDIB DibOpenFile(LPSTR szFile)
  33. {
  34.     HFILE               fh;
  35.     DWORD               dwLen;
  36.     DWORD               dwBits;
  37.     PDIB                pdib;
  38.     LPVOID              p;
  39.     OFSTRUCT            of;
  40.  
  41. #ifdef WIN32
  42.     #define GetCurrentInstance()    GetModuleHandle(NULL)
  43. #else
  44.     #define GetCurrentInstance()    (HINSTANCE)SELECTOROF((LPVOID)&of)
  45. #endif
  46.  
  47.     fh = OpenFile(szFile, &of, OF_READ);
  48.  
  49.     if (fh == -1)
  50.     {
  51.         HRSRC h;
  52.  
  53.         h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);
  54.  
  55. #ifdef WIN32
  56.         //!!! can we call GlobalFree() on this? is it the right format.
  57.         //!!! can we write to this resource?
  58.         return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
  59. #else
  60.         if (h)
  61.             fh = AccessResource(GetCurrentInstance(), h);
  62. #endif
  63.     }
  64.  
  65.     if (fh == -1)
  66.         return NULL;
  67.  
  68.     pdib = DibReadBitmapInfo(fh);
  69.  
  70.     if (!pdib)
  71.         return NULL;
  72.  
  73.     /* How much memory do we need to hold the DIB */
  74.  
  75.     dwBits = pdib->biSizeImage;
  76.     dwLen  = pdib->biSize + DibPaletteSize(pdib) + dwBits;
  77.  
  78.     /* Can we get more memory? */
  79.  
  80.     p = GlobalReAllocPtr(pdib,dwLen,0);
  81.  
  82.     if (!p)
  83.     {
  84.         GlobalFreePtr(pdib);
  85.         pdib = NULL;
  86.     }
  87.     else
  88.     {
  89.         pdib = (PDIB)p;
  90.     }
  91.  
  92.     if (pdib)
  93.     {
  94.         /* read in the bits */
  95.         _hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + DibPaletteSize(pdib), dwBits);
  96.     }
  97.  
  98.     _lclose(fh);
  99.  
  100.     return pdib;
  101. }
  102.  
  103. /*
  104.  *   Write a global handle in CF_DIB format to a file.
  105.  *
  106.  */
  107. BOOL DibWriteFile(PDIB pdib, LPSTR szFile)
  108. {
  109.     BITMAPFILEHEADER    hdr;
  110.     HFILE               fh;
  111.     OFSTRUCT            of;
  112.     DWORD               dwSize;
  113.  
  114.     if (!pdib)
  115.         return FALSE;
  116.  
  117.     fh = OpenFile(szFile,&of,OF_CREATE|OF_READWRITE);
  118.  
  119.     if (fh == -1)
  120.         return FALSE;
  121.  
  122.     dwSize = DibSize(pdib);
  123.  
  124.     hdr.bfType          = BFT_BITMAP;
  125.     hdr.bfSize          = dwSize + sizeof(BITMAPFILEHEADER);
  126.     hdr.bfReserved1     = 0;
  127.     hdr.bfReserved2     = 0;
  128.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + pdib->biSize +
  129.                           DibPaletteSize(pdib);
  130.  
  131.     _lwrite(fh,(LPCSTR)(LPVOID)&hdr,sizeof(BITMAPFILEHEADER));
  132.     _hwrite(fh,(LPCSTR)(LPVOID)pdib,dwSize);
  133.  
  134.     _lclose(fh);
  135.  
  136.     return TRUE;
  137. }
  138.  
  139. /*
  140.  *  CreateBIPalette()
  141.  *
  142.  *  Given a Pointer to a BITMAPINFO struct will create a
  143.  *  a GDI palette object from the color table.
  144.  *
  145.  */
  146. HPALETTE DibCreatePalette(PDIB pdib)
  147. {
  148.     LOGPALETTE         *pPal;
  149.     HPALETTE            hpal = NULL;
  150.     int                 nNumColors;
  151.     int                 i;
  152.     RGBQUAD FAR *       pRgb;
  153.  
  154.     if (!pdib)
  155.         return NULL;
  156.  
  157.     nNumColors = DibNumColors(pdib);
  158.     
  159.     if (nNumColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
  160.         nNumColors = 0;
  161.  
  162.     if (nNumColors > 0)
  163.     {
  164.         pRgb = DibColors(pdib);
  165.         pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  166.  
  167.         if (!pPal)
  168.             goto exit;
  169.  
  170.         pPal->palNumEntries = nNumColors;
  171.         pPal->palVersion    = 0x300;
  172.  
  173.         for (i = 0; i < nNumColors; i++)
  174.         {
  175.             pPal->palPalEntry[i].peRed   = pRgb->rgbRed;
  176.             pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  177.             pPal->palPalEntry[i].peBlue  = pRgb->rgbBlue;
  178.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  179.  
  180.             pRgb++;
  181.         }
  182.  
  183.         hpal = CreatePalette(pPal);
  184.         LocalFree((HLOCAL)pPal);
  185.     }
  186.     else
  187.     {
  188. #ifdef WIN32                 
  189.         HDC hdc = GetDC(NULL);
  190.         hpal = CreateHalftonePalette(hdc);      
  191.         ReleaseDC(NULL, hdc);
  192. #endif          
  193.     }
  194.  
  195. exit:
  196.     return hpal;
  197. }
  198.  
  199. /*
  200.  *  ReadDibBitmapInfo()
  201.  *
  202.  *  Will read a file in DIB format and return a global HANDLE to it's
  203.  *  BITMAPINFO.  This function will work with both "old" and "new"
  204.  *  bitmap formats, but will allways return a "new" BITMAPINFO
  205.  *
  206.  */
  207. PDIB DibReadBitmapInfo(HFILE fh)
  208. {
  209.     DWORD     off;
  210.     HANDLE    hbi = NULL;
  211.     int       size;
  212.     int       i;
  213.     int       nNumColors;
  214.  
  215.     RGBQUAD FAR       *pRgb;
  216.     BITMAPINFOHEADER   bi;
  217.     BITMAPCOREHEADER   bc;
  218.     BITMAPFILEHEADER   bf;
  219.     PDIB               pdib;
  220.  
  221.     if (fh == -1)
  222.         return NULL;
  223.  
  224.     off = _llseek(fh,0L,SEEK_CUR);
  225.  
  226.     if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
  227.         return FALSE;
  228.  
  229.     /*
  230.      *  do we have a RC HEADER?
  231.      */
  232.     if (bf.bfType != BFT_BITMAP)
  233.     {
  234.         bf.bfOffBits = 0L;
  235.         _llseek(fh,off,SEEK_SET);
  236.     }
  237.  
  238.     if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
  239.         return FALSE;
  240.  
  241.     /*
  242.      *  what type of bitmap info is this?
  243.      */
  244.     switch (size = (int)bi.biSize)
  245.     {
  246.         default:
  247.         case sizeof(BITMAPINFOHEADER):
  248.             break;
  249.  
  250.         case sizeof(BITMAPCOREHEADER):
  251.             bc = *(BITMAPCOREHEADER*)&bi;
  252.             bi.biSize               = sizeof(BITMAPINFOHEADER);
  253.             bi.biWidth              = (DWORD)bc.bcWidth;
  254.             bi.biHeight             = (DWORD)bc.bcHeight;
  255.             bi.biPlanes             =  (UINT)bc.bcPlanes;
  256.             bi.biBitCount           =  (UINT)bc.bcBitCount;
  257.             bi.biCompression        = BI_RGB;
  258.             bi.biSizeImage          = 0;
  259.             bi.biXPelsPerMeter      = 0;
  260.             bi.biYPelsPerMeter      = 0;
  261.             bi.biClrUsed            = 0;
  262.             bi.biClrImportant       = 0;
  263.  
  264.             _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  265.  
  266.             break;
  267.     }
  268.  
  269.     nNumColors = DibNumColors(&bi);
  270.  
  271. #if 0
  272.     if (bi.biSizeImage == 0)
  273.         bi.biSizeImage = DibSizeImage(&bi);
  274.  
  275.     if (bi.biClrUsed == 0)
  276.         bi.biClrUsed = DibNumColors(&bi);
  277. #else
  278.     FixBitmapInfo(&bi);
  279. #endif
  280.  
  281.     pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  282.  
  283.     if (!pdib)
  284.         return NULL;
  285.  
  286.     *pdib = bi;
  287.  
  288.     pRgb = DibColors(pdib);
  289.  
  290.     if (nNumColors)
  291.     {
  292.         if (size == sizeof(BITMAPCOREHEADER))
  293.         {
  294.             /*
  295.              * convert a old color table (3 byte entries) to a new
  296.              * color table (4 byte entries)
  297.              */
  298.             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));
  299.  
  300.             for (i=nNumColors-1; i>=0; i--)
  301.             {
  302.                 RGBQUAD rgb;
  303.  
  304.                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  305.                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  306.                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  307.                 rgb.rgbReserved = (BYTE)0;
  308.  
  309.                 pRgb[i] = rgb;
  310.             }
  311.         }
  312.         else
  313.         {
  314.             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
  315.         }
  316.     }
  317.  
  318.     if (bf.bfOffBits != 0L)
  319.         _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  320.  
  321.     return pdib;
  322. }
  323.  
  324. /*
  325.  *  DibFromBitmap()
  326.  *
  327.  *  Will create a global memory block in DIB format that represents the DDB
  328.  *  passed in
  329.  *
  330.  */
  331. PDIB DibFromBitmap(HBITMAP hbm, DWORD biStyle, UINT biBits, HPALETTE hpal, UINT wUsage)
  332. {   
  333.     PDIB                 pdib;
  334.     BITMAP               bm;
  335.     int                  nColors=0;
  336.     HDC                  hdc;
  337.     LPVOID               p;
  338.     UINT                 u;     
  339.  
  340.     if (!hbm)
  341.         return NULL;
  342.  
  343.     if (hpal == NULL)
  344.         hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  345.  
  346.     GetObject(hbm,sizeof(bm),(LPVOID)&bm);
  347.     GetObject(hpal,sizeof(nColors),(LPVOID)&nColors);
  348.  
  349.     if (biBits == 0)
  350.         biBits = bm.bmPlanes * bm.bmBitsPixel;
  351.  
  352.     pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
  353.  
  354.     if (!pdib)
  355.         return NULL;
  356.  
  357.     pdib->biSize               = sizeof(BITMAPINFOHEADER);
  358.     pdib->biWidth              = bm.bmWidth;
  359.     pdib->biHeight             = bm.bmHeight;
  360.     pdib->biPlanes             = 1;
  361.     pdib->biBitCount           = biBits;
  362.     pdib->biCompression        = biStyle;
  363.     pdib->biSizeImage          = 0;
  364.     pdib->biXPelsPerMeter      = 0;
  365.     pdib->biYPelsPerMeter      = 0;
  366.     pdib->biClrUsed            = 0;
  367.     pdib->biClrImportant       = 0;
  368.     pdib->biClrUsed            = DibNumColors(pdib);
  369.  
  370.     // this is a silly hack to test Win32/NT and BI_BITFIELDS
  371.     // convert to a 565 (for 16 bit) or a RGB DIB (for 32/24 bit)
  372.     if (biStyle == BI_BITFIELDS)
  373.     {            
  374.         LPDWORD pdw = (LPDWORD)DibColors(pdib);
  375.                       
  376.         switch (biBits)
  377.         {
  378.             case 16:            
  379.                 pdw[0] = 0xF800;        // masks for RGB 565
  380.                 pdw[1] = 0x07E0;
  381.                 pdw[2] = 0x001F;
  382.                 break;
  383.                                 
  384.             case 24:
  385.             case 32:
  386.                 pdw[0] = 0x0000FF;      // masks for RGB (not normal BGR)
  387.                 pdw[1] = 0x00FF00;
  388.                 pdw[2] = 0xFF0000;
  389.                 break;    
  390.         }
  391.     }   
  392.  
  393.     hdc = CreateCompatibleDC(NULL);
  394.     hpal = SelectPalette(hdc,hpal,FALSE);
  395.     RealizePalette(hdc);
  396.     
  397. #ifdef WIN32                                   
  398.     SetStretchBltMode(hdc, HALFTONE);
  399. #endif    
  400.  
  401.     /*
  402.      *  call GetDIBits with a NULL lpBits param, so it will calculate the
  403.      *  biSizeImage field for us
  404.      */
  405.     GetDIBits(hdc, hbm, 0, (UINT)pdib->biHeight,
  406.         NULL, (LPBITMAPINFO)pdib, wUsage);
  407.  
  408.     pdib->biClrUsed = DibNumColors(pdib);
  409.     pdib->biSizeImage = DibSizeImage(pdib);
  410.  
  411.     /*
  412.      * HACK! if the driver did not fill in the biSizeImage field, make one up
  413.      */
  414.     if (pdib->biSizeImage == 0)
  415.     {
  416.         pdib->biSizeImage = DibSizeImage(pdib);
  417.  
  418.         if (biStyle != BI_RGB)
  419.             pdib->biSizeImage = (pdib->biSizeImage * 3) / 2;
  420.     }
  421.  
  422.     /*
  423.      *  realloc the buffer big enough to hold all the bits
  424.      */
  425.     if (p = GlobalReAllocPtr(pdib,DibSize(pdib),0))
  426.     {
  427.         pdib = (PDIB)p;
  428.     }
  429.     else
  430.     {
  431.         GlobalFreePtr(pdib);
  432.         pdib = NULL;
  433.         goto exit;
  434.     }
  435.  
  436.     /*
  437.      *  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  438.      *  bits this time
  439.      */
  440.     u = GetDIBits(hdc, hbm, 0, (UINT)pdib->biHeight,
  441.         DibPtr(pdib),(LPBITMAPINFO)pdib, wUsage);
  442.  
  443.     pdib->biClrUsed = DibNumColors(pdib);
  444.     pdib->biSizeImage = DibSizeImage(pdib);
  445.     
  446.     // error getting bits.
  447.     
  448.     if (u == 0)
  449.     {
  450.         DibFree(pdib);
  451.         pdib = NULL;
  452.     }   
  453.  
  454. exit:
  455.     SelectPalette(hdc,hpal,FALSE);
  456.     DeleteDC(hdc);
  457.     return pdib;
  458. }
  459.  
  460. /*
  461.  *  BitmapFromDib()
  462.  *
  463.  *  Will create a DDB (Device Dependent Bitmap) given a global handle to
  464.  *  a memory block in CF_DIB format
  465.  *
  466.  */
  467. HBITMAP BitmapFromDib(PDIB pdib, HPALETTE hpal, UINT wUsage)
  468. {
  469.     HPALETTE    hpalT;
  470.     HDC         hdc;
  471.     HBITMAP     hbm;
  472.     DWORD       dwFlags = CBM_INIT;
  473.  
  474.     if (!pdib)
  475.         return NULL;
  476.  
  477. #ifdef WIN32
  478.     if (wUsage == (UINT)-1)     // silly hack for ConvertDib
  479.         if (pdib->biCompression == 0 || 
  480.             pdib->biCompression == BI_BITFIELDS)
  481.         dwFlags |= CBM_CREATEDIB;    
  482. #endif
  483.     if (wUsage == (UINT)-1)
  484.     wUsage = DIB_RGB_COLORS;    // silly hack for ConvertDib
  485.  
  486.     hdc = GetDC(NULL);
  487.  
  488.     if (hpal)
  489.     {
  490.         hpalT = SelectPalette(hdc,hpal,FALSE);
  491.         RealizePalette(hdc);
  492.     }
  493.                     
  494. #ifdef WIN32                                   
  495.     SetStretchBltMode(hdc, HALFTONE);       //??? does this do anything?
  496. #endif    
  497.  
  498.     hbm = CreateDIBitmap(hdc,
  499.                 pdib,dwFlags,
  500.                 DibPtr(pdib),
  501.                 (LPBITMAPINFO)pdib,
  502.                 wUsage);
  503.  
  504.     if (hpal && hpalT)
  505.         SelectPalette(hdc,hpalT,FALSE);
  506.  
  507.     ReleaseDC(NULL,hdc);
  508.  
  509.     return hbm;
  510. }
  511.  
  512. /*
  513.  *  DibSetUsage(hdib,hpal,wUsage)
  514.  *
  515.  *  Modifies the color table of the passed DIB for use with the wUsage
  516.  *  parameter specifed.
  517.  *
  518.  *  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  519.  *  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  520.  *      in the passed palette
  521.  *
  522.  */
  523. BOOL DibSetUsage(PDIB pdib, HPALETTE hpal,UINT wUsage)
  524. {
  525.     PALETTEENTRY       ape[256];
  526.     RGBQUAD FAR *      pRgb;
  527.     WORD FAR *         pw;
  528.     int                nColors;
  529.     int                n;
  530.  
  531.     if (hpal == NULL)
  532.         hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  533.  
  534.     if (!pdib)
  535.         return FALSE;
  536.  
  537.     nColors = DibNumColors(pdib);
  538.     
  539.     if (nColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
  540.         nColors = 0;
  541.  
  542.     if (nColors > 0)
  543.     {
  544.         pRgb = DibColors(pdib);
  545.  
  546.         switch (wUsage)
  547.         {
  548. #ifdef WIN32
  549.             case DIB_PAL_INDICES:
  550.                 // hack!!! fall through  
  551. #endif
  552.             //
  553.             // Set the DIB color table to palette indexes
  554.             //
  555.             case DIB_PAL_COLORS:
  556.                 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
  557.                     *pw = n;
  558.                 break;
  559.  
  560.             //
  561.             // Set the DIB color table to RGBQUADS
  562.             //
  563.             default:
  564.             case DIB_RGB_COLORS:
  565.                 nColors = min(nColors,256);
  566.  
  567.                 GetPaletteEntries(hpal,0,nColors,ape);
  568.  
  569.                 for (n=0; n<nColors; n++)
  570.                 {
  571.                     pRgb[n].rgbRed      = ape[n].peRed;
  572.                     pRgb[n].rgbGreen    = ape[n].peGreen;
  573.                     pRgb[n].rgbBlue     = ape[n].peBlue;
  574.                     pRgb[n].rgbReserved = 0;
  575.                 }
  576.                 break;
  577.         }
  578.     }
  579.     return TRUE;
  580. }
  581.  
  582. /*
  583.  *  DibDraw()
  584.  */
  585. BOOL DibDraw(HDC hdc,  int x,  int y,  int dx,  int dy,
  586.             PDIB pdib, int x0, int y0, int dx0, int dy0,
  587.             LONG rop, UINT wUsage)
  588. {
  589.     BOOL f;
  590.     LPVOID lpBits;
  591.  
  592.     if (!pdib)
  593.         return FALSE;
  594.  
  595.     if (dx0 == -1 && dy0 == -1)
  596.     {
  597.         dx0 = DibWidth(pdib);
  598.         dy0 = DibHeight(pdib);
  599.     }
  600.  
  601.     if (dx == -1 && dy == -1)
  602.     {
  603.     dx = dx0;
  604.     dy = dy0;
  605.     }          
  606.         
  607. #if 0                                   
  608. #ifdef WIN32
  609.     if (pdib->biBitCount > 8)
  610.         SetStretchBltMode(hdc, HALFTONE);
  611.     else
  612.         SetStretchBltMode(hdc, COLORONCOLOR);
  613. #else    
  614.     SetStretchBltMode(hdc, COLORONCOLOR);
  615. #endif    
  616. #endif
  617.  
  618.     lpBits = DibPtr(pdib);
  619.     
  620.     f = StretchDIBits(
  621.         hdc,
  622.         x,y,
  623.         dx,dy,
  624.         x0,y0,
  625.         dx0,dy0,
  626.         lpBits, (LPBITMAPINFO)pdib,
  627.         wUsage,
  628.         rop);
  629.  
  630.     return f;
  631. }
  632.  
  633. PDIB DibCopy(PDIB pdib)
  634. {
  635.     PDIB pdibCopy;
  636.  
  637.     if (pdib == NULL)
  638.         return NULL;
  639.  
  640.     if (pdibCopy = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,DibSize(pdib)))
  641.         hmemcpy(pdibCopy, pdib, DibSize(pdib));
  642.  
  643.     return pdibCopy;
  644. }
  645.  
  646. PDIB DibCreate(int bits, int dx, int dy)
  647. {
  648.     LPBITMAPINFOHEADER lpbi ;
  649.     DWORD       dwSizeImage;
  650.     int         i;
  651.     DWORD FAR  *pdw;
  652.  
  653.     dwSizeImage = dy*(DWORD)((dx*bits/8+3)&~3);
  654.  
  655.     lpbi = (PDIB)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
  656.  
  657.     if (lpbi == NULL)
  658.         return NULL;
  659.  
  660.     lpbi->biSize            = sizeof(BITMAPINFOHEADER) ;
  661.     lpbi->biWidth           = dx;
  662.     lpbi->biHeight          = dy;
  663.     lpbi->biPlanes          = 1;
  664.     lpbi->biBitCount        = bits ;
  665.     lpbi->biCompression     = BI_RGB ;
  666.     lpbi->biSizeImage       = dwSizeImage;
  667.     lpbi->biXPelsPerMeter   = 0 ;
  668.     lpbi->biYPelsPerMeter   = 0 ;
  669.     lpbi->biClrUsed         = 0 ;
  670.     lpbi->biClrImportant    = 0 ;
  671.  
  672.     if (bits == 4)
  673.         lpbi->biClrUsed = 16;
  674.  
  675.     else if (bits == 8)
  676.         lpbi->biClrUsed = 256;
  677.  
  678.     pdw = (DWORD FAR *)((LPBYTE)lpbi+(int)lpbi->biSize);
  679.  
  680.     for (i=0; i<(int)lpbi->biClrUsed/16; i++)
  681.     {
  682.         *pdw++ = 0x00000000;    // 0000  black
  683.         *pdw++ = 0x00800000;    // 0001  dark red
  684.         *pdw++ = 0x00008000;    // 0010  dark green
  685.         *pdw++ = 0x00808000;    // 0011  mustard
  686.         *pdw++ = 0x00000080;    // 0100  dark blue
  687.         *pdw++ = 0x00800080;    // 0101  purple
  688.         *pdw++ = 0x00008080;    // 0110  dark turquoise
  689.         *pdw++ = 0x00C0C0C0;    // 1000  gray
  690.         *pdw++ = 0x00808080;    // 0111  dark gray
  691.         *pdw++ = 0x00FF0000;    // 1001  red
  692.         *pdw++ = 0x0000FF00;    // 1010  green
  693.         *pdw++ = 0x00FFFF00;    // 1011  yellow
  694.         *pdw++ = 0x000000FF;    // 1100  blue
  695.         *pdw++ = 0x00FF00FF;    // 1101  pink (magenta)
  696.         *pdw++ = 0x0000FFFF;    // 1110  cyan
  697.         *pdw++ = 0x00FFFFFF;    // 1111  white
  698.     }
  699.  
  700.     return (PDIB)lpbi;
  701. }
  702.  
  703. PDIB DibConvert(PDIB pdib, int BitCount, DWORD biCompression)
  704. {
  705.     HBITMAP hbm;            
  706.     HPALETTE hpal = NULL;
  707.     
  708.     if (pdib == NULL)
  709.         return NULL;
  710.  
  711.     if (DibNumColors(pdib) > 3)
  712.         hpal = DibCreatePalette(pdib);
  713.     // pass -1 as wUsage so we dont get a device bitmap, see
  714.     // BitmapFromDib for the Hack. NOTE only in Win32
  715.     hbm = BitmapFromDib(pdib, hpal, (UINT)-1 /*DIB_RGB_COLORS*/); 
  716.         
  717.     if (hbm)
  718.         pdib = DibFromBitmap(hbm, biCompression, BitCount, hpal, DIB_RGB_COLORS);
  719.     else
  720.         pdib = NULL;
  721.         
  722.     if (hbm)
  723.         DeleteObject(hbm);
  724.         
  725.     if (hpal)
  726.         DeleteObject(hpal);
  727.         
  728.     return pdib;
  729. }
  730.  
  731.  
  732. static void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  733. {
  734.     DWORD dw;
  735.  
  736.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
  737.         *pb = xlat[*pb];
  738. }
  739.  
  740. static void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  741. {
  742.     DWORD dw;
  743.  
  744.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
  745.         *pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
  746. }
  747.  
  748. #define RLE_ESCAPE  0
  749. #define RLE_EOL     0
  750. #define RLE_EOF     1
  751. #define RLE_JMP     2
  752.  
  753. static void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  754. {
  755.     BYTE    cnt;
  756.     BYTE    b;
  757.     BYTE _huge *prle = pb;
  758.  
  759.     for(;;)
  760.     {
  761.         cnt = *prle++;
  762.         b   = *prle;
  763.  
  764.         if (cnt == RLE_ESCAPE)
  765.         {
  766.             prle++;
  767.  
  768.             switch (b)
  769.             {
  770.                 case RLE_EOF:
  771.                     return;
  772.  
  773.                 case RLE_EOL:
  774.                     break;
  775.  
  776.                 case RLE_JMP:
  777.                     prle++;     // skip dX
  778.                     prle++;     // skip dY
  779.                     break;
  780.  
  781.                 default:
  782.                     cnt = b;
  783.                     for (b=0; b<cnt; b++,prle++)
  784.                         *prle = xlat[*prle];
  785.  
  786.                     if (cnt & 1)
  787.                         prle++;
  788.  
  789.                     break;
  790.             }
  791.         }
  792.         else
  793.         {
  794.             *prle++ = xlat[b];
  795.         }
  796.     }
  797. }
  798.  
  799. static void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  800. {
  801. }
  802.  
  803. static void memmove(BYTE _huge *d, BYTE _huge *s, LONG len)
  804. {
  805.     d += len-1;
  806.     s += len-1;
  807.  
  808.     while (len--)
  809.         *d-- = *s--;
  810. }
  811.  
  812. //
  813. // MapDib - map the given DIB so it matches the specifed palette
  814. //
  815. void DibMapToPalette(PDIB pdib, HPALETTE hpal)
  816. {
  817.     LPBITMAPINFOHEADER  lpbi;
  818.     PALETTEENTRY        pe;
  819.     int                 n;
  820.     int                 nDibColors;
  821.     int                 nPalColors=0;
  822.     BYTE FAR *          lpBits;
  823.     RGBQUAD FAR *       lpRgb;
  824.     BYTE                xlat[256];
  825.     DWORD               SizeImage;
  826.  
  827.     if (!hpal || !pdib)
  828.         return;
  829.  
  830.     lpbi   = (LPBITMAPINFOHEADER)pdib;
  831.     lpRgb  = DibColors(pdib);
  832.  
  833.     GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
  834.     nDibColors = DibNumColors(pdib);
  835.  
  836.     if ((SizeImage = lpbi->biSizeImage) == 0)
  837.         SizeImage = DibSizeImage(lpbi);
  838.  
  839.     //
  840.     //  build a xlat table. from the current DIB colors to the given
  841.     //  palette.
  842.     //
  843.     for (n=0; n<nDibColors; n++)
  844.         xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
  845.  
  846.     lpBits = (LPBYTE)DibPtr(lpbi);
  847.     lpbi->biClrUsed = nPalColors;
  848.  
  849.     //
  850.     // re-size the DIB
  851.     //
  852.     if (nPalColors > nDibColors)
  853.     {
  854.         GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
  855.         memmove((BYTE _huge *)DibPtr(lpbi), (BYTE _huge *)lpBits, SizeImage);
  856.         lpBits = (LPBYTE)DibPtr(lpbi);
  857.     }
  858.     else if (nPalColors < nDibColors)
  859.     {
  860.         hmemcpy(DibPtr(lpbi), lpBits, SizeImage);
  861.         GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
  862.         lpBits = (LPBYTE)DibPtr(lpbi);
  863.     }
  864.  
  865.     //
  866.     // translate the DIB bits
  867.     //
  868.     switch (lpbi->biCompression)
  869.     {
  870.         case BI_RLE8:
  871.             xlatRle8(lpBits, SizeImage, xlat);
  872.             break;
  873.  
  874.         case BI_RLE4:
  875.             xlatRle4(lpBits, SizeImage, xlat);
  876.             break;
  877.  
  878.         case BI_RGB:
  879.             if (lpbi->biBitCount == 8)
  880.                 xlatClut8(lpBits, SizeImage, xlat);
  881.             else
  882.                 xlatClut4(lpBits, SizeImage, xlat);
  883.             break;
  884.     }
  885.  
  886.     //
  887.     //  Now copy the RGBs in the logical palette to the dib color table
  888.     //
  889.     for (n=0; n<nPalColors; n++)
  890.     {
  891.         GetPaletteEntries(hpal,n,1,&pe);
  892.  
  893.         lpRgb[n].rgbRed      = pe.peRed;
  894.         lpRgb[n].rgbGreen    = pe.peGreen;
  895.         lpRgb[n].rgbBlue     = pe.peBlue;
  896.         lpRgb[n].rgbReserved = (BYTE)0;
  897.     }
  898.  
  899.     return;
  900. }
  901.  
  902. void MakeIdentityPalette(HPALETTE hpal)
  903. {
  904.     HDC hdc;
  905.     PALETTEENTRY ape[256];
  906.     HPALETTE hpalT;
  907.     int nColors;
  908.     int nCosmic;
  909.     int i;
  910.     HWND hwnd = GetActiveWindow();
  911.  
  912.     hdc = GetDC(hwnd);
  913.  
  914.     nColors = GetDeviceCaps(hdc, SIZEPALETTE); // should be 256
  915.     nCosmic = GetDeviceCaps(hdc, NUMRESERVED); // should be 20
  916.  
  917.     if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && nColors <= 256)
  918.     {
  919.         hpalT = SelectPalette(hdc, hpal, FALSE);
  920.         RealizePalette(hdc);
  921.  
  922.         GetSystemPaletteEntries(hdc, 0, nColors, ape);
  923.  
  924.         for (i=0; i<nCosmic/2; i++)
  925.             ape[i].peFlags = 0;
  926.  
  927.         for (; i<nColors-nCosmic/2; i++)
  928.             ape[i].peFlags = PC_NOCOLLAPSE;
  929.  
  930.         for (; i<nColors; i++)
  931.             ape[i].peFlags = 0;
  932.  
  933.         ResizePalette(hpal, nColors);
  934.         SetPaletteEntries(hpal, 0, nColors, ape);
  935.     }
  936.  
  937.     ReleaseDC(hwnd,hdc);
  938. }
  939.  
  940. /*
  941.  * CopyPalette, makes a copy of a GDI logical palette
  942.  */
  943. HPALETTE CopyPalette(HPALETTE hpal)
  944. {
  945.     PLOGPALETTE ppal;
  946.     int         nNumEntries=0;
  947.  
  948.     if (!hpal)
  949.         return NULL;
  950.  
  951.     GetObject(hpal,sizeof(int),(LPSTR)&nNumEntries);
  952.  
  953.     if (nNumEntries == 0)
  954.         return NULL;
  955.  
  956.     ppal = (PLOGPALETTE)LocalAlloc(LPTR,sizeof(LOGPALETTE) +
  957.                 nNumEntries * sizeof(PALETTEENTRY));
  958.  
  959.     if (!ppal)
  960.         return NULL;
  961.  
  962.     ppal->palVersion    = 0x0300;
  963.     ppal->palNumEntries = nNumEntries;
  964.  
  965.     GetPaletteEntries(hpal,0,nNumEntries,ppal->palPalEntry);
  966.  
  967.     hpal = CreatePalette(ppal);
  968.  
  969.     LocalFree((HANDLE)ppal);
  970.     return hpal;
  971. }
  972.